package message

import (
	"errors"
	"time"

	"gorm.io/gorm"
)

// Repository 消息仓储接口
type Repository interface {
	// 消息相关
	GetMessageByID(id uint) (*Message, error)
	CreateMessage(message *Message, receiverIDs []uint) error
	UpdateMessage(message *Message) error
	DeleteMessage(id uint) error
	ListMessages(query *MessageQuery) ([]*Message, int64, error)

	// 接收者相关
	GetMessageReceiverByID(id uint) (*MessageReceiver, error)
	GetMessageReceivers(messageID uint) ([]*MessageReceiver, error)
	GetUserMessages(userID uint, query *UserMessageQuery) ([]*MessageWithReceiver, int64, error)
	UpdateMessageStatus(receiverID uint, messageID uint, status int) error
	BatchUpdateMessageStatus(receiverID uint, messageIDs []uint, status int) error
	CountUnreadMessages(receiverID uint) (int64, error)
}

// MessageQuery 消息查询条件
type MessageQuery struct {
	TenantID uint
	SenderID uint
	Type     *int
	Title    string
	PageNum  int
	PageSize int
}

// UserMessageQuery 用户消息查询条件
type UserMessageQuery struct {
	TenantID   uint
	ReceiverID uint
	Status     *int
	Type       *int
	Title      string
	PageNum    int
	PageSize   int
}

// MessageWithReceiver 消息及接收状态
type MessageWithReceiver struct {
	Message
	ReceiverID uint       `json:"receiver_id"`
	Status     int        `json:"status"`
	ReadTime   *time.Time `json:"read_time"`
}

// GormRepository GORM实现的消息仓储
type GormRepository struct {
	db *gorm.DB
}

// NewGormRepository 创建GORM实现的消息仓储
func NewGormRepository(db *gorm.DB) Repository {
	return &GormRepository{db: db}
}

// GetMessageByID 根据ID获取消息
func (r *GormRepository) GetMessageByID(id uint) (*Message, error) {
	var message Message
	if err := r.db.First(&message, id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, ErrMessageNotFound
		}
		return nil, err
	}
	return &message, nil
}

// CreateMessage 创建消息并添加接收者
func (r *GormRepository) CreateMessage(message *Message, receiverIDs []uint) error {
	return r.db.Transaction(func(tx *gorm.DB) error {
		// 创建消息
		if err := tx.Create(message).Error; err != nil {
			return err
		}

		// 添加接收者
		for _, receiverID := range receiverIDs {
			receiver := &MessageReceiver{
				TenantID:   message.TenantID,
				MessageID:  message.ID,
				ReceiverID: receiverID,
				Status:     MessageStatusUnread,
			}
			if err := tx.Create(receiver).Error; err != nil {
				return err
			}
		}

		return nil
	})
}

// UpdateMessage 更新消息
func (r *GormRepository) UpdateMessage(message *Message) error {
	return r.db.Save(message).Error
}

// DeleteMessage 删除消息
func (r *GormRepository) DeleteMessage(id uint) error {
	return r.db.Transaction(func(tx *gorm.DB) error {
		// 删除消息
		if err := tx.Delete(&Message{}, id).Error; err != nil {
			return err
		}

		// 删除关联的接收者记录
		if err := tx.Where("message_id = ?", id).Delete(&MessageReceiver{}).Error; err != nil {
			return err
		}

		return nil
	})
}

// ListMessages 查询消息列表
func (r *GormRepository) ListMessages(query *MessageQuery) ([]*Message, int64, error) {
	db := r.db.Model(&Message{})

	// 应用查询条件
	if query.TenantID > 0 {
		db = db.Where("tenant_id = ?", query.TenantID)
	}
	if query.SenderID > 0 {
		db = db.Where("sender_id = ?", query.SenderID)
	}
	if query.Type != nil {
		db = db.Where("type = ?", *query.Type)
	}
	if query.Title != "" {
		db = db.Where("title LIKE ?", "%"+query.Title+"%")
	}

	// 计算总数
	var total int64
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if query.PageNum > 0 && query.PageSize > 0 {
		offset := (query.PageNum - 1) * query.PageSize
		db = db.Offset(offset).Limit(query.PageSize)
	}

	// 执行查询
	var messages []*Message
	if err := db.Order("created_at DESC").Find(&messages).Error; err != nil {
		return nil, 0, err
	}

	return messages, total, nil
}

// GetMessageReceiverByID 根据ID获取消息接收者
func (r *GormRepository) GetMessageReceiverByID(id uint) (*MessageReceiver, error) {
	var receiver MessageReceiver
	if err := r.db.First(&receiver, id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, ErrReceiverNotFound
		}
		return nil, err
	}
	return &receiver, nil
}

// GetMessageReceivers 获取消息的所有接收者
func (r *GormRepository) GetMessageReceivers(messageID uint) ([]*MessageReceiver, error) {
	var receivers []*MessageReceiver
	if err := r.db.Where("message_id = ?", messageID).Find(&receivers).Error; err != nil {
		return nil, err
	}
	return receivers, nil
}

// GetUserMessages 获取用户的消息列表
func (r *GormRepository) GetUserMessages(userID uint, query *UserMessageQuery) ([]*MessageWithReceiver, int64, error) {
	db := r.db.Table("message_receiver mr").
		Select("m.*, mr.receiver_id, mr.status, mr.read_time").
		Joins("JOIN message m ON mr.message_id = m.id").
		Where("mr.receiver_id = ?", userID)

	// 应用查询条件
	if query.TenantID > 0 {
		db = db.Where("mr.tenant_id = ?", query.TenantID)
	}
	if query.Status != nil {
		db = db.Where("mr.status = ?", *query.Status)
	}
	if query.Type != nil {
		db = db.Where("m.type = ?", *query.Type)
	}
	if query.Title != "" {
		db = db.Where("m.title LIKE ?", "%"+query.Title+"%")
	}

	// 计算总数
	var total int64
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if query.PageNum > 0 && query.PageSize > 0 {
		offset := (query.PageNum - 1) * query.PageSize
		db = db.Offset(offset).Limit(query.PageSize)
	}

	// 执行查询
	var messages []*MessageWithReceiver
	if err := db.Order("m.created_at DESC").Find(&messages).Error; err != nil {
		return nil, 0, err
	}

	return messages, total, nil
}

// UpdateMessageStatus 更新消息状态
func (r *GormRepository) UpdateMessageStatus(receiverID uint, messageID uint, status int) error {
	updates := map[string]interface{}{
		"status": status,
	}

	// 如果是标记为已读，则更新阅读时间
	if status == MessageStatusRead {
		now := time.Now()
		updates["read_time"] = &now
	}

	return r.db.Model(&MessageReceiver{}).
		Where("receiver_id = ? AND message_id = ?", receiverID, messageID).
		Updates(updates).Error
}

// BatchUpdateMessageStatus 批量更新消息状态
func (r *GormRepository) BatchUpdateMessageStatus(receiverID uint, messageIDs []uint, status int) error {
	updates := map[string]interface{}{
		"status": status,
	}

	// 如果是标记为已读，则更新阅读时间
	if status == MessageStatusRead {
		now := time.Now()
		updates["read_time"] = &now
	}

	return r.db.Model(&MessageReceiver{}).
		Where("receiver_id = ? AND message_id IN ?", receiverID, messageIDs).
		Updates(updates).Error
}

// CountUnreadMessages 统计未读消息数量
func (r *GormRepository) CountUnreadMessages(receiverID uint) (int64, error) {
	var count int64
	err := r.db.Model(&MessageReceiver{}).
		Where("receiver_id = ? AND status = ?", receiverID, MessageStatusUnread).
		Count(&count).Error
	return count, err
}
